package cn.tedu.truetaste.service.impl;

import cn.tedu.truetaste.ex.ServiceException;
import cn.tedu.truetaste.ex.handler.ZpwServiceException;
import cn.tedu.truetaste.mapper.CategoryMapper;
import cn.tedu.truetaste.mapper.DishesMapper;
import cn.tedu.truetaste.mapper.SpuMapper;
import cn.tedu.truetaste.pojo.dto.CategoryAddNewDTO;
import cn.tedu.truetaste.pojo.dto.CategoryUpdateDTO;
import cn.tedu.truetaste.pojo.entity.Category;
import cn.tedu.truetaste.pojo.entity.CategoryEntity;
import cn.tedu.truetaste.pojo.vo.CategoryListItemVO;
import cn.tedu.truetaste.pojo.vo.CategoryStandardVO;
import cn.tedu.truetaste.pojo.vo.CategoryTreeVO;
import cn.tedu.truetaste.service.ICategoryService;
import cn.tedu.truetaste.service.IDishesService;
import cn.tedu.truetaste.web.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 处理类别业务实现类
 *
 * @author java@tedu.cn
 * @version 0.0.1
 */
@Slf4j
@Service
public class CategoryServiceImpl implements ICategoryService {

    public static final String CATEGORY_TREE_KEY="category_tree";

    @Autowired
    private ICategoryService categoryService;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SpuMapper spuMapper;

    public CategoryServiceImpl() {
        log.debug("创建业务类对象：CategoryServiceImpl");
    }

    @Override
    public void addNew(CategoryAddNewDTO categoryAddNewDTO) {
        log.debug("开始处理【添加类别】的业务，参数：{}", categoryAddNewDTO);
        // 调用Mapper对象的countByName()检查类别名称是否已经被占用
        String name = categoryAddNewDTO.getName();
        int countByName = categoryMapper.countByName(name);
        if (countByName > 0) {
            // 是：抛出异常（ERR_CONFLICT）
            String message = "添加类别失败，尝试添加的类别名称【" + name + "】已经被占用！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        Integer depth = 1;
        CategoryStandardVO parentCategory = null;
        Long parentId = categoryAddNewDTO.getParentId();
        if (parentId != 0) {
            // 如果parentId不是0，调用Mapper对象的getStandardById()查询类别详情
            parentCategory = categoryMapper.getStandardById(parentId);
            // 判断查询结果是否为null
            if (parentCategory == null) {
                // 是：父级类别不存在，抛出异常（NOT_FOUND）
                String message = "添加类别失败，选定的父级类别不存在！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
            } else {
                depth = parentCategory.getDepth() + 1;
            }
        }

        // 创建Category类的对象
        Category category = new Category();
        // 将参数对象中的各属性值复制到以上新创建的Category类的对象中
        BeanUtils.copyProperties(categoryAddNewDTO, category);
        // 补全Category类的对象的属性值：depth
        category.setDepth(depth);
        // 补全Category类的对象的属性值：isParent >>> 固定为0
        category.setIsParent(0);
        // 调用Mapper对象的insert()方法插入类别数据
        log.debug("即将插入数据：{}", category);
        int rows = categoryMapper.insert(category);
        if (rows != 1) {
            String message = "添加类别失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }

        // 如果现在添加的类别的父级类别不是0
        if (parentId != 0) {
            // 如果父级类别的isParent仍为0
            if (parentCategory.getIsParent() == 0) {
                // 则将父级类别的isParent更新为1
                Category updateParentCategory = new Category();
                updateParentCategory.setId(parentId);
                updateParentCategory.setIsParent(1);
                rows = categoryMapper.update(updateParentCategory);
                if (rows != 1) {
                    String message = "添加类别失败，服务器忙，请稍后再次尝试！";
                    log.warn(message);
                    throw new ServiceException(ServiceCode.ERR_UPDATE, message);
                }
            }
        }
    }

    @Override
    public void delete(Long id) {
        // 调用Mapper对象的getStandardById()执行查询
        CategoryStandardVO currentCategory = categoryMapper.getStandardById(id);
        // 判断查询结果是否为null
        if (currentCategory == null) {
            // 是：数据已经不存在，抛出异常（NOT_FOUND）
            String message = "删除类别失败，尝试删除的类别不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 判断以上查询结果中的isParent是否为1
        if (currentCategory.getIsParent() == 1) {
            // 是：当前尝试删除的是父级类别，抛出异常（CONFLICT）
            String message = "删除类别失败，尝试删除的类别仍包含子级类别！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        {
            // 调用SpuMapper对象的countByCategory()执行统计
            int count = spuMapper.countByCategory(id);
            // 判断统计结果是否大于0
            if (count > 0) {
                // 是：当前尝试删除的类别关联到了某些SPU，抛出异常（CONFLICT）
                String message = "删除类别失败，尝试删除的类别关联了某些SPU！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        // 调用Mapper对象的deleteById()执行删除
        log.debug("即将执行删除类别，参数：{}", id);
        int rows = categoryMapper.deleteById(id);
        if (rows != 1) {
            String message = "删除类别失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }

        // 从此前的查询结果中找到当前删除的类别的父级类别ID
        Long parentId = currentCategory.getParentId();
        // 判断父级类别ID是否不为0
        if (parentId != 0) {
            // 调用Mapper对象的countByParentId()执行统计
            int count = categoryMapper.countByParentId(parentId);
            // 判断统计结果是否等于0
            if (count == 0) {
                // 是：将父级类别的isParent更新为0
                Category parentCategory = new Category();
                parentCategory.setId(parentId);
                parentCategory.setIsParent(0);
                rows = categoryMapper.update(parentCategory);
                if (rows != 1) {
                    String message = "删除类别失败，服务器忙，请稍后再次尝试！";
                    log.warn(message);
                    throw new ServiceException(ServiceCode.ERR_UPDATE, message);
                }
            }
        }
    }

    @Override
    public void setEnable(Long id) {
        updateEnableById(id, 1);
    }

    @Override
    public void setDisable(Long id) {
        updateEnableById(id, 0);
    }

    @Override
    public void setDisplay(Long id) {
        updateDisplayById(id, 1);
    }

    @Override
    public void setHidden(Long id) {
        updateDisplayById(id, 0);
    }

    @Override
    public void updateInfoById(Long id, CategoryUpdateDTO categoryUpdateDTO) {
        log.debug("开始处理【修改类别详情】的业务，参数ID：{}，新数据：{}",id, categoryUpdateDTO);

        {
            // 调用Mapper的getStandardById()执行查询，检查数据是否不存在
            CategoryStandardVO category = categoryMapper.getStandardById(id);
            // 是：数据不存在，抛出异常
            if (category == null) {
                String message = "修改类别详情失败，尝试访问的数据不存在！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
            }
        }

        {
            // 调用Mapper的countByNameAndNotId()执行查询，检查新的名称是否已经被别的数据占用
            int count = categoryMapper.countByNameAndNotId(id, categoryUpdateDTO.getName());
            // 是：名称被别的数据占用，抛出异常（NOT_CONFLICT）
            if (count > 0) {
                String message = "修改类别详情失败，新的类别名称已经被占用！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        // 创建category对象
        Category category = new Category();
        // 将参数对象的属性值复制到以上新创建的category对象中
        BeanUtils.copyProperties(categoryUpdateDTO, category);
        category.setId(id);
        category.setParentId(0L);
        category.setDepth(1);
        category.setIsParent(1);
        category.setIsDisplay(1);
        // 调用Mapper的update(Category category)方法执行修改
        log.debug("即将执行修改数据，参数：{}", category);
        int rows = categoryMapper.update(category);
        if (rows != 1) {
            String message = "修改类别详情失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    @Override
    public CategoryStandardVO getStandardById(Long id) {
        log.debug("开始处理【根据id查询类别详情】的业务，参数：{}", id);
        CategoryStandardVO category = categoryMapper.getStandardById(id);
        if (category == null) {
            // 是：此id对应的数据不存在，则抛出异常(ERR_NOT_FOUND)
            String message = "查询类别详情失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        return category;
    }

    @Override
    public List<CategoryListItemVO> listByParentId(Long parentId) {
        log.debug("开始处理【根据父级查询子级类别列表】的业务，参数：{}", parentId);
        List<CategoryListItemVO> list = categoryMapper.listByParentId(parentId);
        return list;
    }

    private void updateEnableById(Long id, Integer enable) {
        String enableText[] = {"禁用", "启用"};
        log.debug("开始处理【{}类别】的业务，ID：{}，目标状态：{}", enableText[enable], id, enableText);
        // 调用Mapper对象的getStandardById()方法执行查询
        CategoryStandardVO queryResult = categoryMapper.getStandardById(id);
        // 判断查询结果是否为null
        if (queryResult == null) {
            // 是：抛出异常（NOT_FOUND）
            String message = enableText[enable] + "类别失败，尝试访问的类别数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

//         判断以上查询结果中的enable是否与参数enable相同
        if (queryResult.getEnable().equals(enable)) {
            // 是：抛出异常（CONFLICT）
            String message = enableText[enable] + "类别失败，当前类别已经处理" + enableText[enable] + "状态！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        // 创建Category对象，并将2个参数的值封装进来
        Category category = new Category();
        category.setId(id);
        category.setEnable(enable);
        // 调用Mapper对象的update()执行更新，并获取返回结果，判断是否符合预期值
        int rows = categoryMapper.update(category);
        if (rows != 1) {
            String message = enableText[enable] + "类别失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    private void updateDisplayById(Long id, Integer isDisplay) {
        String[] displayText = {"隐藏", "显示"};
        log.debug("开始处理【{}类别】的业务，ID：{}，目标状态：{}", displayText[isDisplay], id, isDisplay);
        // 检查数据是否存在
        CategoryStandardVO queryResult = categoryMapper.getStandardById(id);
        if (queryResult == null) {
            String message = displayText[isDisplay] + "类别失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 检查当前状态是否与参数表示的状态相同
        if (queryResult.getIsDisplay().equals(isDisplay)) {
            String message = displayText[isDisplay] + "类别失败，当前类别已经处于" + displayText[isDisplay] + "状态！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        // 准备执行更新
        Category category = new Category();
        category.setId(id);
        category.setIsDisplay(isDisplay);
        log.debug("即将修改数据，参数：{}", category);
        int rows = categoryMapper.update(category);
        if (rows != 1) {
            String message = displayText[isDisplay] + "类别失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    @Override
    public CategoryTreeVO categoryTree() {
        if (redisTemplate.hasKey(CATEGORY_TREE_KEY)){
            CategoryTreeVO<CategoryEntity> treeVO= (CategoryTreeVO<CategoryEntity>)
                    redisTemplate.boundValueOps(CATEGORY_TREE_KEY).get();
            return treeVO;
        }
        List<CategoryStandardVO> categoryList=categoryService
                .getCategoryList();

        CategoryTreeVO<CategoryEntity> treeVO=
                initTree(categoryList);
        redisTemplate.boundValueOps(CATEGORY_TREE_KEY).set(
                treeVO,
                1,
                TimeUnit.MINUTES);
        return treeVO;
    }

    @Override
    public List<CategoryStandardVO> getCategoryList() {
        return categoryMapper.selectAllCategories();
    }


    private CategoryTreeVO<CategoryEntity> initTree(List<CategoryStandardVO> categoryList) {
        Map<Long,List<CategoryEntity>> map=new HashMap<>();
        log.info("准备构建三级分类树,分类对象数量为:{}",categoryList.size());
        for (CategoryStandardVO categoryStandardVO : categoryList){
            CategoryEntity categoryEntity=new CategoryEntity();
            BeanUtils.copyProperties(categoryStandardVO,categoryEntity);
            Long parentId=categoryEntity.getParentId();
            if (!map.containsKey(parentId)){
                List<CategoryEntity> value=new ArrayList<>();
                value.add(categoryEntity);
                map.put(parentId,value);
            }else{
                map.get(parentId).add(categoryEntity);
            }
        }
        List<CategoryEntity> cLevels=map.get(0L);
        if (cLevels==null || cLevels.isEmpty()){
            throw new ZpwServiceException(
                    ServiceCode.ERR_INSERT,"没有一级分类对象！");
        }
        for (CategoryEntity oneLevel : cLevels){
            Long secondLevelParentId=oneLevel.getId();
            List<CategoryEntity> secondLevels=map.get(secondLevelParentId);
            if (secondLevels==null || secondLevels.isEmpty()){
                log.warn("当前二级分类没有内容:{}",secondLevelParentId);
                continue;
            }
            for (CategoryEntity twoLevel : secondLevels){
                Long thirdLevelParentId= twoLevel.getId();
                List<CategoryEntity> thirdLevels=map.get(thirdLevelParentId);

                if(thirdLevels==null || thirdLevels.isEmpty()){
                    log.warn("当前二级分类没有三级分类内容:{}",thirdLevelParentId);
                    continue;
                }
                twoLevel.setChildrens(thirdLevels);
            }
            oneLevel.setChildrens(secondLevels);
        }
        CategoryTreeVO<CategoryEntity> treeVO=
                new CategoryTreeVO<>();
        treeVO.setCategories(cLevels);
        // 最后千万别忘了返回treeVO!!!
        return treeVO;
    }
}
